<?php
/**
 * Class and Function List:
 * Function list:
 * - getMin()
 * - addDay()
 * - addHour()
 * - getDayOfWeek()
 * - getTimeOfDay()
 * - getListForQuery()
 * - countAssoc()
 * - getHomeLink()
 * - getCurrentLink()
 * - redirect()
 * - isValidDate()
 * - isValidDBDate()
 * - dateToUnixTimeStamp()
 * - convertDateToMySQLStyle()
 * - convertDateToDisplayStyle()
 * - getDayNameMapping()
 * - getFrenchDayName()
 * - convertToTimezone()
 * - convertToGMT()
 * - isCEST()
 * - calculateLinearRegression()
 * - calculate2ndOrderPolynomialRegression()
 * - generateMD5()
 * - uploadFile()
 */
class Utils
{
    function getMin($a, $b)
    {
        return ($a < $b) ? $a : $b;

    }
    function addDay($day, $date = "", $format = "Y-m-d")
    {
        if ($date == "") $date = date("Y-m-d");
        $time = strtotime($date);
        $addTime = mktime(0, 0, 0, date("m", $time) , $day+date("d", $time) , date("Y", $time));
        return date($format, $addTime);

    }
    function addHour($hour, $date = "", $format = "Y-m-d H:00")
    {
        if ($date == "") $date = date("Y-m-d");
        $time = strtotime($date);
        $addTime = mktime($hour+date("H", $time) , 0, 0, date("m", $time) , date("d", $time) , date("Y", $time));
        return date($format, $addTime);

    }
    function getDayOfWeek($date = "")
    {
        if ($date == "") $date = date("Y-m-d");
        return date("w", strtotime($date));

    }
    function getTimeOfDay($date = "")
    {
        if ($date == "") $date = date("Y-m-d");
        return intval(date("H", strtotime($date)));

    }
    // create a list string from an array for database query
    // output format: ('value-1', 'value-2', ..., 'value-n')
    function getListForQuery($arr)
    {
        $list = "(";
        foreach($arr as $value) $list.= "'$value', ";
        $list = substr($list, 0, -2);
        $list.= ")";
        return $list;

    }
    // count the number of value in an 2 dimensional-associative array
    function countAssoc($arr)
    {
        return count($arr, COUNT_RECURSIVE) -count($arr);

    }
    function getHomeLink()
    {
		return ADMIN_HOME;
    }
    function getCurrentLink()
    {
        return $_SERVER['REQUEST_URI'];

    }
    function redirect($url)
    {
        header("Location: " . $url);
        exit();

    }
    /*
    function convertEncoding(&$data)
    {
    if( is_string($data) )
    $data = utf8_decode(trim($data));
    elseif( is_array($data))
    {
    foreach( $data as $key => $value )
    Utils::convertEncoding($data[$key]);
    }
    }
    */
    function isValidDate($date, $french_type = true)
    {
        if (!preg_match('/^[0-9]{1,2}[\/][0-9]{1,2}[\/][0-9]{2,4}$/', $date)) return FALSE;
        if ($french_type) list($day, $month, $year) = preg_split('/[\/-]/', $date);
        else list($month, $day, $year) = preg_split('/[\/-]/', $date);
        return checkdate($month, $day, $year);

    }
    function isValidDBDate($date)
    {
        list($year, $month, $day) = preg_split('/[\/-]/', $date);
        return checkdate(intval($month) , intval($day) , intval($year));

    }
    function dateToUnixTimeStamp($date, $french_type = true)
    {
        if (!self::isValidDate($date, $french_type)) return FALSE;
        if ($french_type) list($day, $month, $year) = preg_split('/[\/-]/', $date);
        else list($month, $day, $year) = preg_split('/[\/-]/', $date);
        return mktime(0, 0, 0, $month, $day, $year);

    }
    function convertDateToMySQLStyle($date, $french_type = true)
    {
        if (!self::isValidDate($date, $french_type)) return '';
        return date('Y-m-d', Utils::dateToUnixTimeStamp($date, $french_type));

    }
    function convertDateToDisplayStyle($date, $french_type = true)
    {
        if( preg_match('/[\/-]/', $date) )
        {
        if ($date == '') return '';
        list($year, $month, $day) = preg_split('/[\/-]/', $date);
        //echo "$year, $month, $day";
        //exit();
        $tmp_date = mktime(0, 0, 0, intval($month) , intval($day) , intval($year));
        //echo "$tmp_date";
        //exit();
        }
        else
        {
        	$tmp_date = $date;
        }

        if ($french_type)
        {
            return date('d/m/Y', $tmp_date);

        }
        return date('m/d/Y', $tmp_date);

    }
    function getDayNameMapping()
    {
        return array(
            0 => _LB_MONDAY,
            1 => _LB_TUESDAY,
            2 => _LB_WEDNESDAY,
            3 => _LB_THURSDAY,
            4 => _LB_FRIDAY,
            5 => _LB_SATURDAY,
            6 => _LB_SUNDAY,
            7 => _LB_DAYOFF
        );

    }
    function getFrenchDayName($ordinal_number = 0)
    {
        $daynames = Utils::getDayNameMapping();
        return $daynames[$ordinal_number];

    }

    function roundMinute($minute)
    {
    	return $minute >= 30 ? "30" : "00";
    }

    function checkExist( $checking_in_objects = array(), $keyname = 'ID', $keyValue)
    {
    	foreach( $checking_in_objects as $cio )
        {
            $obj = new $cio;
            $obj->selectAdd();
            $obj->selectAdd('COUNT(*) as NBRECORD');
            $obj->whereAdd($keyname . ' = ' .mysql_real_escape_string($keyValue));
            $obj->find();
            $obj->fetch();

            if( isset($obj->NBRECORD) && $obj->NBRECORD > 0 )
                return true;
        }
        return false;
    }

    /**
     * Check if the text string max length is valided
     *
     * @param string $text
     * @param int $length
     * @return true if $text length is not excceed $length; false otherwise
     */

    function isValidLength($text, $length)
    {
		if (is_null($text) || mb_strlen($text) > $length)
		{
			return false;
		}
		else
		{
			return true;
		}
    }
     /**
     * Check if the text string min length is valided
     *
     * @param string $text
     * @param int $length
     * @return true if $text length is more $length long; false otherwise
     */

    function isValidMinLength($text, $length)
    {
		if (is_null($text) || mb_strlen($text) < $length)
		{
			return false;
		}
		else
		{
			return true;
		}
    }

    /**
     * Check text input is valid
     *
     * @param string $text
     * @param boolean true if text input is valid
     */    
    function textvalid($text)
	{
		if (trim($text) == "" || $text == null ||  strlen($text) == 0)
			return false;
		else
			return true;
	}
	
	/**
	 * Format number for save DB, 2 decimal, save for double field
	 *
	 * @param unknown_type $number
	 * @return formated_number
	 */
	function format_number_db($number)
	{
		// exp: xxxx.xx - 1234.12
		return number_format($number, 2, '.', '');
	}
	
	/**
	 * Convert a GMT time to another timezone
	 *
     * @param string $str_datetime is the given timestamp at GMT 0
	 * @param integer $offset is the offset of the destination timezone
	 * @param boolean $is_dst whether this timezone is affected by DST
     * @return time $timestamp the converted timestamp at the destimation timezone 	
	 */
	static public function convertToTimezone($str_datetime, $offset, $is_dst = false)
	{
		$origin_datetime = strtotime($str_datetime);
		
		if ($origin_datetime === false)
			return false;
		else
		{
			$after_datetime = $origin_datetime + $offset;
			
			if ($is_dst !== false)
			{
				if ( isCEST($origin_datetime) )
					return ($after_datetime + 3600);
				else
					return $after_datetime;
			}
		}
	}
	
	/**
	 * Convert a time from another timezone to GMT 0
	 *
     * @param string $str_datetime is the given timestamp at the original timezone
	 * @param integer $offset is the offset of the original timezone
	 * @param boolean $is_dst whether this timezone is affected by DST
     * @return time $timestamp the converted timestamp at GMT 0
	 */
	static public function convertToGMT($str_datetime, $offset, $is_dst = false)
	{
		$origin_datetime = strtotime($str_datetime);
		
		if ($origin_datetime === false)
			return false;
		else
		{
			$after_datetime = $origin_datetime - $offset;
			
			if ($is_dst !== false)
			{
				if ( isCEST($after_datetime) )
					return ($after_datetime - 3600);
				else
					return $after_datetime;
			}
		}
	}
	
	/**
	 * Check if a given time is in CEST time
	 *
     * @param time $datetime is the given timestamp at GMT 0
	 * @return true, if the given timestamp is in CEST (1:00 GMT 0 of last Sunday of March to before 1:00 GMT 0 of last Sunday of October)
	 * false, otherwise
	 */
	static public function isCEST($datetime)
	{
		$dayweek = date("N", $datetime);  // day of week
		$daymonth = date("d", $datetime);  // day of month
		$month = date("m", $datetime);  // month
		$year = date("Y", $datetime);  // year
		
		if (($month < 3) or ($month > 10))
			return false;
		
		if ($month == 3) 
		{
			$tempday = mktime( 1, 0, 0, 3, 31, $year);
			$temp_dayweek = date("N", $tempday);
			
			while ($temp_dayweek != 7)
			{
				$tempday -= 86400;
				$temp_dayweek = date("N", $tempday);
			}
			
			if ($datetime >= $tempday)
				return true;
			else
				return false;
		}
		
		if ($month == 10)
		{
			$tempday = mktime( 1, 0, 0, 10, 31, $year);
			$temp_dayweek = date("N", $tempday);
			
			while ($temp_dayweek != 7)
			{
				$tempday -= 86400;
				$temp_dayweek = date("N", $tempday);
			}
			
			if ($datetime < $tempday)
				return true;
			else
				return false;	
		}
		
		return true;
	}

    /**
     * Calculate linear regression on a dataset
     * @param array $data The data to calculate regression upon
     * @return array The slope and intersection of the "best-fit" line and the coefficient of determination
     */    
    function calculateLinearRegression(&$data)
    {
        $sumX = 0; 
        $sumY = 0;
        foreach ($data as $point) {
            $sumX += $point['X'];
            $sumY += $point['Y'];
        }        
        $meanX = $sumX / count($data);
        $meanY = $sumY / count($data);

        $sumXX = 0;
        $sumYY = 0;
        $sumXY = 0;
        foreach ($data as $point) {
            $sumXX += ($point['X'] - $meanX) * ($point['X'] - $meanX);
            $sumYY += ($point['Y'] - $meanY) * ($point['Y'] - $meanY);
            $sumXY += ($point['X'] - $meanX) * ($point['Y'] - $meanY);
        }        

        $result = array();
		if ($sumXX == 0)
			$result['slope'] = 0;
		else
		   $result['slope'] = ($sumXY / $sumXX);      
        $result['intersection'] = $meanY - ($result['slope'] * $meanX);
		
		$x = 0;
		$sum_err = 0;
        foreach ($data as $point) {
			$x++;
			$fi = $result['slope']  * $x + $result['intersection'];
			$sum_err += ($point['Y'] - $fi) * ($point['Y'] - $fi);
		}
		
		if ($sumYY == 0)
		   $result['R2'] = 1; 
		else
		   $result['R2'] = 1 - ($sum_err / $sumYY);        
		
		return $result;
    }

	/**
	 * Calculate second-order polynomial regression on a dataset
	 * @param array $data is the data to calculate regression upon
     * @return array includes 3 parameters of the 2nd-order polynomial function and the coefficient of determination
	 */	 
	 public static function calculate2ndOrderPolynomialRegression(&$data)
	 {
	 	// Optimize input data
	 	$n = count($data);
		$flag = array_fill(0, $n, false);
		
		$data_result = array();
		for ($i = 0; $i < $n; $i++ ) {
			if (!$flag[$i]) {			
				for ($j = $i + 1; $j < $n; $j++) {
					if ($data[$i]['X'] == $data[$j]['X'] && $data[$i]['Y'] == $data[$j]['Y']) {
						$flag[$j] = true;
					}
				}				
				$data_result[] = $data[$i]	;
			}	
		}
		
		$result = array();

		if (count($data_result) >= 3) {	// In case we have at least 3 different input data
			$dataX = array();
			$dataY = array();	 	
			
			foreach ($data_result as $point) {			
				$temp = array();
				$temp[] = 1;
				$temp[] = $point['X'];
				$temp[] = $point['X'] * $point['X'];
				
				$dataX[] = $temp;
				
				$temp = array();
				$temp[] = $point['Y'];
				
				$dataY[] = $temp;
			}
			
			include_once('Math/Matrix/Matrix.php');
			
			$matrix_transpose = new Math_Matrix($dataX); 
			$matrix_transpose1 = new Math_Matrix($dataX);
			$matrix = new Math_Matrix($dataX);  // matrix X
			$matrixY = new Math_Matrix($dataY);  // matrix Y
			
			$matrix_transpose->transpose();  // transposition of matrix X
			$matrix_transpose1->transpose(); // temporary of matrix X's transposition
			
			$matrix_transpose->multiply($matrix);  // Xt * X
			
			$matrix_transpose->invert();  // invert(Xt * X) 
			
			$matrix_transpose->multiply($matrix_transpose1);  // invert(Xt * X) * Xt
			
			$matrix_transpose->multiply($matrixY);  // beta = invert(Xt * X) * Xt * Y
			
			$temp = $matrix_transpose->getData();  // get the result
			
			$result['a'] = $temp[2][0];
			$result['b'] = $temp[1][0];
			$result['c'] = $temp[0][0];

			// calculate the coefficient of determination
			$sumY = 0;
			foreach ($data as $point) {
				$sumY += $point['Y'];
			}
			$meanY = $sumY / count($data);
			
			$sumYY = 0;
			$sum_err = 0;
			foreach ($data as $point) {
				$sumYY += ($point['Y'] - $meanY) * ($point['Y'] - $meanY);
				$fi = $result['a'] * $point['X'] * $point['X'] + $result['b'] * $point['X'] + $result['c'];
				$sum_err += ($point['Y'] - $fi) * ($point['Y'] - $fi);
			}
			
			if ($sumYY != 0)
				$result['R2'] = 1 - ($sum_err / $sumYY);
			else
				$result['R2'] = 1;
		}
		else {
			$temp_result = Utils::calculateLinearRegression($data_result);
			
			$result['a'] = 0;
			$result['b'] = $temp_result['slope'];
			$result['c'] = $temp_result['intersection'];
			$result['R2'] = $temp_result['R2'];
		}		
			
		return $result;
	 }
	 
	//-- 2008-02-19
	function addMinute($minute, $date = "", $format = "Y-m-d H:i:00")
    {
        if ($date == "") $date = date("Y-m-d");
        $time = strtotime($date);
		$time += intval($minute) * 60 ;        
        return date($format, $time);

    }
    
	function isInvalidDecimalNumber($number, $number_decimal, $exa = 0)
	{
		if(!$number_decimal)
		{
			$number_decimal = 2;
		}
		
		if($number == 0)
		{
			return true;
		}			
			
		if($number)
		{			
			$temp = explode(".",$number);

			if(count($temp)>1)
			{
				if($exa == 0)
				{
					return (strlen($temp[1]) <= $number_decimal);
				}
				else 
				{
					return (strlen($temp[1]) == $number_decimal);
				}				
			}
			else if($exa == 0)
			{
				return true;
			}
		}
		return false;
	}
	
	public static function generateMD5($str = NULL) {
		if (empty($str)) {
			return md5(rand(0,99) . md5(microtime()));
		} else {
			return md5($str);
		}
		
	}
	
	/**
	 *
	 * Store a uploaded file to local disk
	 * 
	 * @param string $upload_dir path to the folder store the uploaded file
	 * @param mixed $posted_file is return value of $_FILES['filename']
	 * @param string $new_file the file name of the uploaded file. If it's empty, a md5 string will be generated as new file name
	 * @param string $old_file the file name is deleted if uploading is success
	 * @return string Return new file name if upload success, else return FALSE
	 */
	
	public static function uploadFile($upload_dir, $posted_file, $new_file = '', $old_file = '') {
		if (empty($posted_file) || empty($posted_file['name'])) {
			return FALSE;
		}
		$path_info = pathinfo($posted_file['name']);
		$file_ext = $path_info['extension'];

		// create $upload_dir if not exist
		if (!file_exists($upload_dir)) {
			mkdir($upload_dir, 0777, true);
		}

		// generate $new_file if 
		if (empty($new_file)) {
			$new_file = Utils::generateMD5().'.'.$file_ext;
		}

		if (move_uploaded_file($posted_file["tmp_name"], "$upload_dir/$new_file")) {
			if ($old_file && $new_file != $old_file) {
				@unlink("$upload_dir/$old_file");
			}
			return $new_file;
		} else {
			return FALSE;
		}
	}
    public function RemoveSign($str)
    {
        $coDau=array("à","á","ạ","ả","ã","â","ầ","ấ","ậ","ẩ","ẫ","ă","ằ","ắ"
        ,"ặ","ẳ","ẵ","è","é","ẹ","ẻ","ẽ","ê","ề","ế","ệ","ể","ễ","ì","í","ị","ỉ","ĩ",
        "ò","ó","ọ","ỏ","õ","ô","ồ","ố","ộ","ổ","ỗ","ơ"
        ,"ờ","ớ","ợ","ở","ỡ",
        "ù","ú","ụ","ủ","ũ","ư","ừ","ứ","ự","ử","ữ",
        "ỳ","ý","ỵ","ỷ","ỹ",
        "đ",
        "À","Á","Ạ","Ả","Ã","Â","Ầ","Ấ","Ậ","Ẩ","Ẫ","Ă"
        ,"Ằ","Ắ","Ặ","Ẳ","Ẵ",
        "È","É","Ẹ","Ẻ","Ẽ","Ê","Ề","Ế","Ệ","Ể","Ễ",
        "Ì","Í","Ị","Ỉ","Ĩ",
        "Ò","Ó","Ọ","Ỏ","Õ","Ô","Ồ","Ố","Ộ","Ổ","Ỗ","Ơ"
        ,"Ờ","Ớ","Ợ","Ở","Ỡ",
        "Ù","Ú","Ụ","Ủ","Ũ","Ư","Ừ","Ứ","Ự","Ử","Ữ",
        "Ỳ","Ý","Ỵ","Ỷ","Ỹ",
        "Đ","ê","ù","à");
        $khongDau=array("a","a","a","a","a","a","a","a","a","a","a"
        ,"a","a","a","a","a","a",
        "e","e","e","e","e","e","e","e","e","e","e",
        "i","i","i","i","i",
        "o","o","o","o","o","o","o","o","o","o","o","o"
        ,"o","o","o","o","o",
        "u","u","u","u","u","u","u","u","u","u","u",
        "y","y","y","y","y",
        "d",
        "A","A","A","A","A","A","A","A","A","A","A","A"
        ,"A","A","A","A","A",
        "E","E","E","E","E","E","E","E","E","E","E",
        "I","I","I","I","I",
        "O","O","O","O","O","O","O","O","O","O","O","O"
        ,"O","O","O","O","O",
        "U","U","U","U","U","U","U","U","U","U","U",
        "Y","Y","Y","Y","Y",
        "D","e","u","a");
        $special_char = array("?","/","\\",":","!","`","_","-",'"',".",",","  ","(",")");
        $empty = array("","","","","","","-","",'',"",""," ","","");
        $url = str_replace($coDau,$khongDau,$str);
        $url = str_replace($special_char,$empty,trim($url));
        return strtolower(str_replace(" ","-",$url)).".html";
    }
}
?>
